using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Enums;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Infrastructure.Data;

namespace UniversalAdmin.Infrastructure.Repositories;

public class ArticleRepository : BaseRepository<Article>, IArticleRepository
{
  public ArticleRepository(UniversalAdminDbContext context) : base(context) { }

  public async Task<(IEnumerable<Article> Items, int TotalCount)> GetPagedArticlesAsync(
      string? keyword = null,
      int? categoryId = null,
      ArticleStatus? status = null,
      int pageIndex = 1,
      int pageSize = 10)
  {
    var query = _context.Articles
        .Include(a => a.Category)
        .Include(a => a.User)
        .AsQueryable();

    if (!string.IsNullOrWhiteSpace(keyword))
    {
      query = query.Where(a =>
          a.Title.Contains(keyword) ||
          a.Summary.Contains(keyword));
    }

    if (categoryId.HasValue)
    {
      query = query.Where(a => a.CategoryId == categoryId.Value);
    }

    if (status != null)
    {
      query = query.Where(a => a.Status == status);
    }

    var totalCount = await query.CountAsync();

    var items = await query
        .OrderByDescending(a => a.CreatedAt)
        .Skip((pageIndex - 1) * pageSize)
        .Take(pageSize)
        .AsNoTracking()
        .ToListAsync();

    return (items, totalCount);
  }

  public async Task<(IEnumerable<Article> Items, int TotalCount)> SearchArticlesAsync(
      string? keyword = null,
      ArticleStatus? status = null,
      DateTime? start = null,
      DateTime? end = null,
      int pageIndex = 1,
      int pageSize = 10,
      CancellationToken ct = default)
  {
    IQueryable<Article> query = _context.Articles
        .Include(a => a.User)     // Author
        .Include(a => a.Category) // Category
        .OrderByDescending(a => a.CreatedAt);

    if (!string.IsNullOrWhiteSpace(keyword))
      query = query.Where(a => a.Title.Contains(keyword));

    if (status.HasValue)
      query = query.Where(a => a.Status == status.Value);

    if (start.HasValue)
      query = query.Where(a => a.CreatedAt >= start.Value);

    if (end.HasValue)
      query = query.Where(a => a.CreatedAt <= end.Value);

    var total = await query.CountAsync(ct);
    var items = await query
        .Skip((pageIndex - 1) * pageSize)
        .Take(pageSize)
        .AsNoTracking()
        .ToListAsync(ct);

    return (items, total);
  }
}